package cc.owoo.godpen.analysis.html;

import cc.owoo.godpen.analysis.Retract;
import cc.owoo.godpen.file.SuperFile;

import java.io.File;
import java.io.IOException;

/**
 * HTML Document解析
 * Created by nimensei
 * 2022-05-21 上午 01:58
 **/
public class Document extends Element {
    private final ElementMap idMap = new ElementMap(ElementMap.ElementType.ELEMENT);// id子元素映射表
    String doctype;// 文本类型
    String lang;// HTML标注的语言

    public final Element head;// head
    public final Element body;// body

    public Document() {
        super("html");
        head = new Element("head");
        body = new Element("body");
        appendChild(head);
        appendChild(body);
    }


    /**
     * 读取File中的文本，并解析HTML
     *
     * @param file 需要解析的HTML文件
     * @return 解析后的Document元素
     */
    public static Document parse(File file) {
        if (file == null)
            return new Document();
        try {
            return parse(SuperFile.readText(file));
        } catch (IOException e) {
            return new Document();
        }
    }

    /**
     * 解析HTML
     *
     * @param html 需要解析的HTML文本
     * @return 解析后的Document元素
     */
    public static Document parse(String html) {
        Document document = new Document();
        if (html != null)
            new HtmlAnalysis(document, new HtmlStringAnalysis(html.toCharArray())).analysis();
        return document;
    }

    /**
     * 创建元素
     *
     * @param tagName 元素标签名称
     * @return 元素对象
     */
    public static Element createElement(String tagName) {
        if (tagName == null || tagName.length() == 0)
            throw new IllegalArgumentException("标签名称不能为空: " + tagName);
        char first = tagName.charAt(0);
        if (!(first >= 'a' && first <= 'z' || first >= 'A' && first <= 'Z'))
            throw new IllegalArgumentException("标签名称的第一个符号必须为英文字母: " + tagName);
        for (char c : tagName.toCharArray())
            if (c <= 32)
                throw new IllegalArgumentException("标签名称中不能包含空格: " + tagName);
        return new Element(tagName);
    }

    /**
     * 设置属性
     *
     * @param property 属性值
     */
    void setProperty(String[] property) {
        if (property == null || property.length < 2)
            return;
        if (property[0].equalsIgnoreCase("doctype"))
            doctype = property[1].toLowerCase();
    }

    @Override
    void onUpdateID(String old, String now, Element element) {
        super.onUpdateID(old, now, element);
        idMap.remove(old, element);
        idMap.add(now, element);
    }

    @Override
    void appendRecord(Element element) {
        super.appendRecord(element);
        if (element.getId() != null)
            idMap.add(element.getId(), element);
    }

    @Override
    void removeRecord(Element element) {
        super.removeRecord(element);
        idMap.remove(element.getId(), element);
    }

    /**
     * 获取头部元素
     *
     * @return 头部元素
     */
    public Element getHead() {
        return head;
    }

    /**
     * 获取body
     *
     * @return body元素
     */
    public Element getBody() {
        return body;
    }


    /**
     * 根据标签ID获取元素
     *
     * @param id 标签ID
     * @return 元素对象
     */
    public Element getElementById(String id) {
        return idMap.get(id).get(0);
    }

    @Override
    public Document getDocument() {
        return this;
    }

    @Override
    void stringify(StringBuilder string, boolean root, Retract retract, boolean isOriginal) {
        if (root) {
            string.append("<!DOCTYPE html>");
            if (retract.isEnable())
                string.append('\n');
        }
        super.stringify(string, root, retract, isOriginal);
    }
}
